package com.ssy.lingxi.product.serviceImpl.material;

import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.tree.Node;
import com.ssy.lingxi.common.constant.tree.TreeUtils;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.product.entity.Goods;
import com.ssy.lingxi.product.entity.material.MaterialGroup;
import com.ssy.lingxi.product.model.request.MaterialGroupChangeParentRequest;
import com.ssy.lingxi.product.repository.GoodsRepository;
import com.ssy.lingxi.product.repository.material.MaterialGroupRepository;
import com.ssy.lingxi.product.service.material.IMaterialGroupService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 物料组-serviceImpl
 *
 * @author hsl
 * @version 2.0.0
 * @date 22/03/22 16:49
 */
@Service
public class MaterialGroupServiceImpl implements IMaterialGroupService {
    @Resource
    private MaterialGroupRepository materialGroupRepository;
    @Resource
    private GoodsRepository goodsRepository;

    @Override
    public Wrapper<List<Node>> getMaterialGroupTree(UserLoginCacheDTO sysUser, Long rootNodeId, Long excludeId) {
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();
        List<MaterialGroup> materialGroupList;
        if (rootNodeId != null && rootNodeId > 0) {
            materialGroupList = materialGroupRepository.findByMemberIdAndMemberRoleIdAndFullIdStartingWith(memberId, memberRoleId, String.format(Constants.CATEGORY_FULL_ID_NUM, rootNodeId));
        } else {
            materialGroupList = materialGroupRepository.findByMemberIdAndMemberRoleId(memberId, memberRoleId);
        }
        //list过滤
        if (excludeId != null) {
            materialGroupList = materialGroupList.stream().filter(materialGroup -> !materialGroup.getId().equals(excludeId)).collect(Collectors.toList());
        }
        if (!materialGroupList.isEmpty()) {
            //组装树结构
            List<Node> sourceList = materialGroupList.stream().map(c -> new Node(String.valueOf(c.getId()), String.valueOf(c.getParentId()), c.getName(), false, null, null, null, new ArrayList<>())).collect(Collectors.toList());
            List<Node> resultList = materialGroupList.stream().filter(c -> c.getLevel() == 1).map(c -> new Node(String.valueOf(c.getId()), String.valueOf(c.getParentId()), c.getName(), false, null, null, null, new ArrayList<>())).collect(Collectors.toList());
            return Wrapper.success(TreeUtils.buildTree(sourceList, resultList));
        } else {
            return Wrapper.success(new ArrayList<>());
        }
    }

    @Override
    public MaterialGroup getMaterialGroup(Long id) {
        return materialGroupRepository.findById(id).orElse(null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> saveOrUpdateMaterialGroup(UserLoginCacheDTO sysUser, MaterialGroup materialGroup) {
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();
        Long userId = sysUser.getUserId();
        Long id = materialGroup.getId();
        String name = materialGroup.getName();
        Long parentId = materialGroup.getParentId();
        Integer level;
        String parentFullId = "";
        Long currentParentId = null;
        MaterialGroup currentMaterialGroup = null;
        boolean isSameName;
        //新增修改物料组前置校验
        if (id != null) {
            currentMaterialGroup = materialGroupRepository.findById(id).orElse(null);
            if (currentMaterialGroup == null) {
                throw new BusinessException(ResponseCode.MATERIAL_GROUP_NOT_EXIST);
            }
            currentParentId = currentMaterialGroup.getParentId();
            materialGroup.setFullId(currentMaterialGroup.getFullId());
            level = currentMaterialGroup.getLevel();
            isSameName = materialGroupRepository.existsByMemberIdAndMemberRoleIdAndLevelAndNameAndParentIdAndIdNot(memberId, memberId, level, name, currentParentId, id);
        } else {
            if (parentId != null && parentId > 0) {
                MaterialGroup parent = materialGroupRepository.findById(parentId).orElse(null);
                if (parent != null) {
                    level = parent.getLevel() + 1;
                    parentFullId = parent.getFullId();

                } else {
                    throw new BusinessException(ResponseCode.MATERIAL_GROUP_PARENT_NOT_EXIST);
                }
            } else {
                level = 1;

            }
            isSameName = materialGroupRepository.existsByMemberIdAndMemberRoleIdAndLevelAndName(memberId, memberId, level, name);
            materialGroup.setFullId("");
        }

        if (isSameName) {
            throw new BusinessException(ResponseCode.MATERIAL_GROUP_NAME_EXIST);
        }

        materialGroup.setMemberId(memberId);
        materialGroup.setMemberRoleId(memberRoleId);
        materialGroup.setMemberName(sysUser.getCompany());
        materialGroup.setMemberRoleName(sysUser.getMemberRoleName());
        materialGroup.setUserId(userId);
        materialGroup.setUserName(sysUser.getUserName());
        materialGroup.setLevel(level);

        //新增物料组
        if (id == null) {
            materialGroupRepository.saveAndFlush(materialGroup);
            //新增额外再次组装fullId保存
            if (StringUtils.isNotBlank(parentFullId)) {
                materialGroup.setFullId(parentFullId + Constants.SPLIT_STR_FULL_ID + String.format(Constants.CATEGORY_FULL_ID_NUM, materialGroup.getId()));
            } else {
                materialGroup.setFullId(String.format(Constants.CATEGORY_FULL_ID_NUM, materialGroup.getId()));
            }
            materialGroupRepository.saveAndFlush(materialGroup);
        } else {
            //更新时如果修改了上级
            if (!currentParentId.equals(parentId)) {
                //查询当前所有物料组
                List<MaterialGroup> list = materialGroupRepository.findByMemberIdAndMemberRoleIdAndFullIdStartingWithAndIdNot(memberId, memberRoleId, currentMaterialGroup.getFullId(), id);

                //不可作为自己原先下级的下级
                if (list.stream().anyMatch(m -> parentId.equals(m.getId()))) {
                    throw new BusinessException(ResponseCode.MATERIAL_GROUP_SUB_NOT_BE_PARENT);
                }
                //新父级
                Integer parentLevel;
                if (parentId == 0) {
                    parentFullId = "";
                    parentLevel = 0;
                } else {
                    MaterialGroup parent = materialGroupRepository.findById(parentId).orElse(null);
                    if (parent == null) {
                        throw new BusinessException(ResponseCode.MATERIAL_GROUP_PARENT_NOT_EXIST);
                    }
                    parentLevel = parent.getLevel();
                    parentFullId = parent.getFullId() + Constants.SPLIT_STR_FULL_ID;
                }
                MaterialGroup currentParent = materialGroupRepository.findById(currentParentId).orElse(null);
                //下级修改
                if (!CollectionUtils.isEmpty(list)) {
                    int i = materialGroup.getLevel() - parentLevel - 1;
                    for (MaterialGroup group : list) {
                        group.setFullId(currentParent == null ? parentFullId + group.getFullId() : parentFullId + StringUtils.removeStart(group.getFullId(), currentParent.getFullId() + Constants.SPLIT_STR_FULL_ID));
                    }
                }


                materialGroup.setParentId(parentId);
                materialGroup.setFullId(parentFullId + String.format(Constants.CATEGORY_FULL_ID_NUM, materialGroup.getId()));
                materialGroup.setLevel(parentLevel + 1);
                list.add(materialGroup);
                materialGroupRepository.saveAll(list);

            } else {
                //不更新上级只修改信息
                materialGroupRepository.saveAndFlush(materialGroup);
            }
        }

        //成功返回信息
        return Wrapper.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> changeParent(UserLoginCacheDTO sysUser, MaterialGroupChangeParentRequest materialGroupChangeParentRequst) {
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();

        Long id = materialGroupChangeParentRequst.getId();
        Long parentId = materialGroupChangeParentRequst.getParentId();
        MaterialGroup materialGroup = materialGroupRepository.findById(id).orElse(null);

        if (materialGroup == null) {
            throw new BusinessException(ResponseCode.MATERIAL_GROUP_NOT_EXIST);
        }

        Long oldParentId = materialGroup.getParentId();

        if (oldParentId.equals(parentId)) {
            throw new BusinessException(ResponseCode.MATERIAL_GROUP_PARENT_REPETITION);
        }

        MaterialGroup oldParent = materialGroupRepository.findById(materialGroup.getParentId()).orElse(null);

        //查询当前所有物料组
        List<MaterialGroup> list = materialGroupRepository.findByMemberIdAndMemberRoleIdAndFullIdStartingWithAndIdNot(memberId, memberRoleId, materialGroup.getFullId(), id);

        //不可作为自己原先下级的下级
        if (list.stream().anyMatch(m -> parentId.equals(m.getId()))) {
            throw new BusinessException(ResponseCode.MATERIAL_GROUP_SUB_NOT_BE_PARENT);
        }

        //修改parenId ，fullId，level
        //新父级
        String parentFullId;
        Integer parentLevel;
        if (parentId == 0) {
            parentFullId = "";
            parentLevel = 0;
        } else {
            MaterialGroup parent = materialGroupRepository.findById(parentId).orElse(null);
            if (parent == null) {
                throw new BusinessException(ResponseCode.MATERIAL_GROUP_PARENT_NOT_EXIST);
            }
            parentLevel = parent.getLevel();
            parentFullId = parent.getFullId() + Constants.SPLIT_STR_FULL_ID;
        }

        //下级修改
        if (!CollectionUtils.isEmpty(list)) {
            int i = materialGroup.getLevel() - parentLevel - 1;
            list.forEach(m -> {
                m.setFullId(oldParent == null ? parentFullId + m.getFullId() : parentFullId + StringUtils.removeStart(m.getFullId(), oldParent.getFullId() + Constants.SPLIT_STR_FULL_ID));
                m.setLevel(m.getLevel() - i);
            });
        }

        materialGroup.setParentId(parentId);
        materialGroup.setFullId(parentFullId + String.format(Constants.CATEGORY_FULL_ID_NUM, materialGroup.getId()));
        materialGroup.setLevel(parentLevel + 1);
        list.add(materialGroup);
        materialGroupRepository.saveAll(list);

        return Wrapper.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> delete(UserLoginCacheDTO sysUser, Long id) {

        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();

        MaterialGroup materialGroup = materialGroupRepository.findById(id).orElse(null);
        if (materialGroup != null) {
            //判断是否存在子节点
            List<MaterialGroup> subs = materialGroupRepository.findByMemberIdAndMemberRoleIdAndParentId(memberId, memberRoleId, id);
            if (!subs.isEmpty()) {
                throw new BusinessException(ResponseCode.MATERIAL_GROUP_HAVESUB_NOT_DELETE);
            }
            //判断是否有物料还在使用
            List<Goods> goods = goodsRepository.findByMaterialGroupId(id);
            if (!CollectionUtils.isEmpty(goods)) {
            return Wrapper.fail(ResponseCode.PRODUCT_MATERIEL_RELATION_NOT_DELETE);
            }

            materialGroupRepository.deleteById(id);

            return Wrapper.success();
        }
        throw new BusinessException(ResponseCode.MATERIAL_GROUP_NOT_EXIST);

    }

}
